/*
 * GiveTakeTextConfigFileConstructors.java
 *
 * Created on 15 de Junho de 2011, 15:50
 *
 */

package intopo.game.impl.givetake;

import intopo.evogame.partnerselection.config.ParsingException;
import intopo.game.AbstractDescriptionText;


import intopo.game.DescriptionGUI;
import intopo.game.DescriptionText;
import intopo.game.gui.AbstractGameEditorComponent;
import intopo.game.gui.AbstractStrategyEditorComponent;
import intopo.game.gui.AbstractGlobalParametersComponent;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.HashMap;
import java.util.Scanner;

/**
 * Provides a description of the Give-Take game and its strategies.
 *
 * <p> This description is used to construct instances of the game and of its
 * strategies.  It is used to read global parameters used by all instances.
 *
 * @author <a href="mailto:mariano.pedro@gmail.com">Pedro Mariano</a>
 *
 * @version 1.0 15 de Junho de 2011
 */
final public class GiveTakeDescriptionTextGUI
	extends intopo.game.AbstractDescriptionText<GiveTakeGame, GiveTakeStrategy>
	implements
		DescriptionGUI<GiveTakeGame, GiveTakeStrategy>,
		DescriptionText<GiveTakeGame, GiveTakeStrategy>
{
	/**
	 * Instance of this class used by classes in package {@code intopo.evogame.partnerselection}.
	 * 
	 * @see intopo.evogame.partnerselection
	 */
	final private static GiveTakeDescriptionTextGUI instance = new GiveTakeDescriptionTextGUI ();

	/**
	 * Return a map that associates tag names to game constructors. The text file should have a single tag whose name is a key of the returned map.
	 */
	static private Map<String, Constructor<? extends GiveTakeGame>> gameConstructors ()
	{
		Map<String, Constructor<? extends GiveTakeGame>> result;
		Constructor<? extends GiveTakeGame> cg;
		result = new HashMap<String, Constructor<? extends GiveTakeGame>> ();
		try {
			Class<GiveTakeGame> c = GiveTakeGame.class;
			cg = c.getConstructor (Scanner.class);
			result.put (GiveTakeGame.CONSTRUCTOR_ANA_TAG, cg);
		}
		catch (NoSuchMethodException nsme) {
			System.err.println ("Class GiveTakeGame does not have a constructor with parameter type java.util.Scanner");
			System.exit (1);
		}
		try {
			Class<GiveTakeSimulationGame> c = GiveTakeSimulationGame.class;
			cg = c.getConstructor (Scanner.class);
			result.put (GiveTakeSimulationGame.CONSTRUCTOR_SIM_TAG, cg);
		}
		catch (NoSuchMethodException nsme) {
			System.err.println ("Class GiveTakeGame does not have a constructor with parameter type java.util.Scanner");
			System.exit (1);
		}
		return result;
	}
	/**
	 * Return a map that associates tag names to strategy constructors.
	 */
	static private Map<String, Constructor<? extends GiveTakeStrategy>> strategyConstructors ()
	{
		Map<String, Constructor<? extends GiveTakeStrategy>> result;
		Constructor<? extends GiveTakeStrategy> cp;
		result = new HashMap<String, Constructor<? extends GiveTakeStrategy>> ();
		try {
			Class<GiveTakeProbabilisticStrategy> c = GiveTakeProbabilisticStrategy.class;
			cp = c.getConstructor (Scanner.class);
			result.put (GiveTakeProbabilisticStrategy.CONSTRUCTOR_TAG, cp);
		}
		catch (NoSuchMethodException nsme) {
			System.err.println ("Class GiveTakeProbabilisticPlayer does not have a constructor with parameter type java.util.Scanner");
			System.exit (1);
		}
		try {
			Class<GiveTakeDeterministicStrategy> c = GiveTakeDeterministicStrategy.class;
			cp = c.getConstructor (Scanner.class);
			result.put (GiveTakeDeterministicStrategy.CONSTRUCTOR_TAG, cp);
		}
		catch (NoSuchMethodException nsme) {
			System.err.println ("Class GiveTakeDeterministicPlayer does not have a constructor with parameter type java.util.Scanner");
			System.exit (1);
		}
		return result;
	}

	public static GiveTakeDescriptionTextGUI getInstance ()
	{
		return instance;
	}

	@Override
	public String getBinDescription (Class<? extends GiveTakeStrategy> c, int bin)
	{
		if (c.getCanonicalName ().equals ("intopo.game.impl.givetake.GiveTakeDeterministicStrategy")) {
			return GiveTakeDeterministicStrategy.getBinDescription (bin);
		}
		else if (c.getCanonicalName ().equals ("intopo.game.impl.givetake.GiveTakeProbabilisticStrategy")) {
			return GiveTakeProbabilisticStrategy.getBinDescription (bin);
		}
		else {
			throw new Error ("Class " + c.getCanonicalName ()
				+ " does not have a bin description method or method getBinDescription() of class "
				+ this.getClass ().getCanonicalName () + " is not updated");
		}
	}

	@Override
	public void readGlobalParameters (Scanner scanner)
		throws ParsingException
	{
		GiveTakeDeterministicStrategy.Parameters.read (scanner);
		GiveTakeProbabilisticStrategy.Parameters.read (scanner);
	}
	@Override
	public void writeGlobalParameters (PrintStream ps)
	{
		GiveTakeDeterministicStrategy.Parameters.write (ps);
		GiveTakeProbabilisticStrategy.Parameters.write (ps);
	}
	/**
	 * Creates a new instance of GiveTakeTextConfigFileConstructors
	 */
	public GiveTakeDescriptionTextGUI ()
	{
		super (gameConstructors (), strategyConstructors (), new FoldGiveTakeStrategy ());
	}

	@Override
	public AbstractGameEditorComponent<GiveTakeGame, GiveTakeStrategy> getGameEditorComponent ()
	{
		return new GiveTakeGameComponent ();
	}

	@Override
	public AbstractStrategyEditorComponent<GiveTakeStrategy> getStrategyEditorComponent ()
	{
		return new GiveTakeStrategyComponent ();
	}

	@Override
	public AbstractGlobalParametersComponent getGlobalParametersEditorComponent ()
	{
		return new GiveTakeGlobalParametersComponent ();
	}
}
